package org.altervista.cp.thinbcgen.bean.test;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import org.apache.bcel.Constants;
import org.apache.bcel.generic.ClassGen;
import org.apache.bcel.generic.ConstantPoolGen;
import org.apache.bcel.generic.FieldGen;
import org.apache.bcel.generic.InstructionFactory;
import org.apache.bcel.generic.InstructionHandle;
import org.apache.bcel.generic.InstructionList;
import org.apache.bcel.generic.MethodGen;
import org.apache.bcel.generic.Type;

public class JavaBeanCreator implements Constants {
	private InstructionFactory _factory;
	private ConstantPoolGen _cp;
	private ClassGen _cg;

	public JavaBeanCreator() {
		_cg = new ClassGen(
				"org.altervista.cp.thinbcgen.bean.test.JavaBean",
				"java.lang.Object",
				"JavaBean.java",
				ACC_PUBLIC | ACC_SUPER,
				new String[] { "org.altervista.cp.thinbcgen.bean.test.JavaBeanInterf" });

		_cp = _cg.getConstantPool();
		_factory = new InstructionFactory(_cg, _cp);
	}

	public void create(OutputStream out) throws IOException {
		createFields();
		createMethod_0();
		createMethod_1();
		createMethod_2();
		createMethod_3();
		createMethod_4();
		_cg.getJavaClass().dump(out);
	}

	private void createFields() {
		FieldGen field;

		field = new FieldGen(ACC_PRIVATE, Type.STRING, "_name", _cp);
		_cg.addField(field.getField());

		field = new FieldGen(ACC_PRIVATE, Type.DOUBLE, "_price", _cp);
		_cg.addField(field.getField());
	}

	private void createMethod_0() {
		InstructionList il = new InstructionList();
		MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID, Type.NO_ARGS,
				new String[] {}, "<init>",
				"org.altervista.cp.thinbcgen.bean.test.JavaBean", il, _cp);

		InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0));
		il.append(_factory.createInvoke("java.lang.Object", "<init>",
				Type.VOID, Type.NO_ARGS, Constants.INVOKESPECIAL));
		InstructionHandle ih_4 = il.append(_factory.createReturn(Type.VOID));
		method.setMaxStack();
		method.setMaxLocals();
		_cg.addMethod(method.getMethod());
		il.dispose();
	}

	private void createMethod_1() {
		InstructionList il = new InstructionList();
		MethodGen method = new MethodGen(ACC_PUBLIC, Type.STRING, Type.NO_ARGS,
				new String[] {}, "getName",
				"org.altervista.cp.thinbcgen.bean.test.JavaBean", il, _cp);

		InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0));
		il.append(_factory.createFieldAccess(
				"org.altervista.cp.thinbcgen.bean.test.JavaBean", "_name",
				Type.STRING, Constants.GETFIELD));
		InstructionHandle ih_4 = il.append(_factory.createReturn(Type.OBJECT));
		method.setMaxStack();
		method.setMaxLocals();
		_cg.addMethod(method.getMethod());
		il.dispose();
	}

	private void createMethod_2() {
		InstructionList il = new InstructionList();
		MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID,
				new Type[] { Type.STRING }, new String[] { "arg0" }, "setName",
				"org.altervista.cp.thinbcgen.bean.test.JavaBean", il, _cp);

		InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0));
		il.append(_factory.createLoad(Type.OBJECT, 1));
		il.append(_factory.createFieldAccess(
				"org.altervista.cp.thinbcgen.bean.test.JavaBean", "_name",
				Type.STRING, Constants.PUTFIELD));
		InstructionHandle ih_5 = il.append(_factory.createReturn(Type.VOID));
		method.setMaxStack();
		method.setMaxLocals();
		_cg.addMethod(method.getMethod());
		il.dispose();
	}

	private void createMethod_3() {
		InstructionList il = new InstructionList();
		MethodGen method = new MethodGen(ACC_PUBLIC, Type.DOUBLE, Type.NO_ARGS,
				new String[] {}, "getPrice",
				"org.altervista.cp.thinbcgen.bean.test.JavaBean", il, _cp);

		InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0));
		il.append(_factory.createFieldAccess(
				"org.altervista.cp.thinbcgen.bean.test.JavaBean", "_price",
				Type.DOUBLE, Constants.GETFIELD));
		InstructionHandle ih_4 = il.append(_factory.createReturn(Type.DOUBLE));
		method.setMaxStack();
		method.setMaxLocals();
		_cg.addMethod(method.getMethod());
		il.dispose();
	}

	private void createMethod_4() {
		InstructionList il = new InstructionList();
		MethodGen method = new MethodGen(ACC_PUBLIC, Type.VOID,
				new Type[] { Type.DOUBLE }, new String[] { "arg0" },
				"setPrice", "org.altervista.cp.thinbcgen.bean.test.JavaBean",
				il, _cp);

		InstructionHandle ih_0 = il.append(_factory.createLoad(Type.OBJECT, 0));
		il.append(_factory.createLoad(Type.DOUBLE, 1));
		il.append(_factory.createFieldAccess(
				"org.altervista.cp.thinbcgen.bean.test.JavaBean", "_price",
				Type.DOUBLE, Constants.PUTFIELD));
		InstructionHandle ih_5 = il.append(_factory.createReturn(Type.VOID));
		method.setMaxStack();
		method.setMaxLocals();
		_cg.addMethod(method.getMethod());
		il.dispose();
	}

	public static void main(String[] args) throws Exception {
		org.altervista.cp.thinbcgen.bean.test.JavaBeanCreator creator = new org.altervista.cp.thinbcgen.bean.test.JavaBeanCreator();
		creator.create(new FileOutputStream(
				"org.altervista.cp.thinbcgen.bean.test.JavaBean.class"));
	}
}
